package Day020_NIO_AIO.demo1_Selector选择器.Test1_Selector选择器;

import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;

/**
 * @author zhangyan
 * @date 2020/5/13 9:19
 */
/*
    Selector被称为：选择器，也被称为：多路复用器，它可以注册到很多个Channel上，监听各个Channel上发生的事件，
    并且能够根据事件情况决定Channel读写。这样，通过一个线程管理多个Channel，就可以处理大量网络连接了。

    Selector选择器对象的获取:
          Selector selector = Selector.open();

    注册Channel到Selector
            channel.configureBlocking(false);
            SelectionKey key =channel.register(selector,SelectionKey.OP_READ);

    注意，注册的Channel 必须设置成异步模式才可以,否则异步IO就无法工作，这就意味着我们不能把一个FileChannel注册到Selector，
    因为FileChannel没有异步模式，但是网络编程中的SocketChannel是可以的。

    register()方法的第二个参数：是一个int值，意思是在通过Selector监听Channel时对什么事件感兴趣。可以监听四种不同类型的事件，
    而且可以使用SelectionKey的四个常量表示：
            1. 连接就绪--常量：SelectionKey.OP_CONNECT
            2. 接收就绪--常量：SelectionKey.OP_ACCEPT (ServerSocketChannel在注册时只能使用此项)
            3. 读就绪--常量：SelectionKey.OP_READ
            4. 写就绪--常量：SelectionKey.OP_WRITE

    注意：对于ServerSocketChannel在注册时，只能使用OP_ACCEPT，否则抛出异常
         ServerSocketChannel要设置成非阻塞

 */
public class Test2_选择器Selector {
    public static void main(String[] args) throws Exception{

        //Selector选择器对象的获取
        Selector selector = Selector.open();

        //获取ServerSocketChannel对象
        ServerSocketChannel ssc = ServerSocketChannel.open();
        //绑定端口号
        ssc.bind(new InetSocketAddress(666));
        //设置非阻塞
        ssc.configureBlocking(false);

        //把服务器通道的accept()交给选择器处理
        //注册Channel到Selector
        SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT);
    }
}
